package main

import (
	"fmt"

	"github.com/gomodule/redigo/redis"
)

var pool *redis.Pool

func init() {
	// 实例化一个连接池
	pool = &redis.Pool{
		MaxIdle:     16,  // 最大的空闲连接数
		MaxActive:   0,   // 最大的激活连接数(0表示按需自动分配)
		IdleTimeout: 300, // 连接关闭超时时间300s
		Dial: func() (redis.Conn, error) { // 连接的redis数据库
			return redis.Dial("tcp", "localhost:6379")
		},
	}
}

func redisExample() {
	/*
		// 1. 连接redis服务器：127.0.0.1:6379
		c, err := redis.Dial("tcp", "localhost:6379")
		if err != nil {
			fmt.Println("conn redis failed: ", err)
			return
		}
		fmt.Println("redis connect succeeded")
		defer c.Close()
	*/
	// 1. 使用连接池
	// a. 从连接池中取一个连接
	c := pool.Get()
	// b. 使用完成后，将连接返回连接池
	defer c.Close()

	// 2. String类型Set和GET操作
	// a. 设置key
	_, err := c.Do("Set", "abc", 100)
	if err != nil {
		fmt.Println("set key failed: ", err)
		return
	}
	// b. 获取key，并使用Int将字符串转为整型
	r, err := redis.Int(c.Do("get", "abc"))
	if err != nil {
		fmt.Println("get key failed: ", err)
	}
	fmt.Println("get: ", r)

	// 3. String类型批量操作
	_, err = c.Do("mset", "abc", 200, "efg", 300)
	if err != nil {
		fmt.Println("mset keys failed: ", err)
		return
	}
	m, err := redis.Ints(c.Do("mget", "abc", "efg"))
	if err != nil {
		fmt.Println("mget keys failed: ", err)
	}
	fmt.Println("mget: ", m)

	// 4. 设置过期时间，10s后如果获取"abc"，就返回"nil"
	_, err = c.Do("expire", "abc", 10)
	if err != nil {
		fmt.Println("expire key failed: ", err)
		return
	}

	// 5. List类型操作
	// a. 插入数据到列表头部
	_, err = c.Do("lpush", "book_list", "abc", "efg", 300)
	if err != nil {
		fmt.Println("lpush key failed: ", err)
		return
	}
	// b. 弹出数据
	l, err := redis.String(c.Do("lpop", "book_list"))
	if err != nil {
		fmt.Println("lpop key failed: ", err)
		return
	}
	fmt.Println("lpop: ", l)

	// 6. 哈希表操作
	_, err = c.Do("hset", "books", "book1", 100, "book2", 200)
	if err != nil {
		fmt.Println("hset key failed: ", err)
		return
	}
	h, err := redis.Int(c.Do("hget", "books", "book1"))
	if err != nil {
		fmt.Println("hget key failed: ", err)
		return
	}
	fmt.Println("hget: ", h)

	// 7. 连接池
	// a. 在init中实例化
	// b. 关闭连接池
	pool.Close()
}
